package cn.exrick.xboot.modules.assessment.serviceimpl;

import cn.exrick.xboot.common.utils.CustomPage;
import cn.exrick.xboot.common.utils.RestTemplateUtil;
import cn.exrick.xboot.common.utils.SecurityUtil;
import cn.exrick.xboot.common.vo.Result;
import cn.exrick.xboot.common.vo.SearchVo;
import cn.exrick.xboot.config.properties.RestTemplateProperties;
import cn.exrick.xboot.flow.VO.FlowNodeinfoOnInstanceInfoVo;
import cn.exrick.xboot.flow.VO.InitiatorDateTypeVo;
import cn.exrick.xboot.flow.entity.FlowHistory;
import cn.exrick.xboot.flow.entity.FlowInstanceinfo;
import cn.exrick.xboot.flow.entity.FlowNodeinfo;
import cn.exrick.xboot.flow.entity.FlowTaskInstance;
import cn.exrick.xboot.flow.mapper.FlowHistoryMapper;
import cn.exrick.xboot.flow.mapper.FlowInstanceinfoMapper;
import cn.exrick.xboot.flow.mapper.FlowNodeinfoMapper;
import cn.exrick.xboot.flow.mapper.FlowTaskHandlerMapper;
import cn.exrick.xboot.flow.service.IFlowTaskInstanceService;
import cn.exrick.xboot.flow.service.IFlowTemplateinfoUserAuthService;
import cn.exrick.xboot.modules.assessment.dao.HkAssessmentInfoDao;
import cn.exrick.xboot.modules.assessment.dao.HkAssessmentScoreDao;
import cn.exrick.xboot.modules.assessment.entity.HkAssessmentInfo;
import cn.exrick.xboot.modules.assessment.entity.HkAssessmentScore;
import cn.exrick.xboot.modules.assessment.mapper.HkAssessmentInfoMapper;
import cn.exrick.xboot.modules.assessment.service.HkAssessmentInfoService;
import cn.exrick.xboot.modules.assessment.vo.*;
import cn.exrick.xboot.modules.base.entity.User;
import cn.exrick.xboot.modules.base.utils.DateUtils;
import cn.exrick.xboot.modules.content.dao.HontUserDao;
import cn.exrick.xboot.modules.content.entity.HontUser;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.base.Joiner;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.http.*;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;

import org.springframework.web.client.RestTemplate;

import javax.persistence.criteria.*;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;


/**
 * 绩效信息表接口实现
 *
 * @author yck
 */
@Slf4j
@Service
@Transactional
public class HkAssessmentInfoServiceImpl implements HkAssessmentInfoService {

    @Autowired
    private HkAssessmentInfoDao hkAssessmentInfoDao;
    @Autowired
    private HkAssessmentScoreDao hkAssessmentScoreDao;
    @Autowired
    private FlowNodeinfoMapper flowNodeinfoMapper;
    @Autowired
    private HkAssessmentInfoMapper hkAssessmentInfoMapper;
    @Autowired
    private FlowInstanceinfoMapper flowInstanceinfoMapper;
    @Autowired
    private HontUserDao hontUserDao;
    @Autowired
    private FlowHistoryMapper flowHistoryMapper;
    @Autowired
    private FlowTaskHandlerMapper flowTaskHandlerMapper;
    @Autowired
    private IFlowTaskInstanceService flowTaskInstanceService;
    @Autowired
    private IFlowTemplateinfoUserAuthService flowTemplateinfoUserAuthService;
    @Autowired
    private SecurityUtil securityUtil;

    @Override
    public HkAssessmentInfoDao getRepository() {
        return hkAssessmentInfoDao;
    }

    @Override
    public Page<HkAssessmentInfo> findByCondition(HkAssessmentInfo hkAssessmentInfo, SearchVo searchVo, Pageable pageable) {

        return hkAssessmentInfoDao.findAll(new Specification<HkAssessmentInfo>() {
            @Nullable
            @Override
            public Predicate toPredicate(Root<HkAssessmentInfo> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {

                // TODO 可添加你的其他搜索过滤条件 默认已有创建时间过滤
                Path<Date> createTimeField = root.get("createTime");

                List<Predicate> list = new ArrayList<Predicate>();

                // 创建时间
                if (StrUtil.isNotBlank(searchVo.getStartDate()) && StrUtil.isNotBlank(searchVo.getEndDate())) {
                    Date start = DateUtil.parse(searchVo.getStartDate());
                    Date end = DateUtil.parse(searchVo.getEndDate());
                    list.add(cb.between(createTimeField, start, DateUtil.endOfDay(end)));
                }

                Predicate[] arr = new Predicate[list.size()];
                cq.where(list.toArray(arr));
                return null;
            }
        }, pageable);
    }

    @Override
    public CustomPage getHkAssessmentInfoAndFlow(HkAssessmentInfoAndFlowQueryVo vo) {
        CustomPage page = new CustomPage();
        page.setPageNumber(vo.getPageNumber());
        page.setPageSize(vo.getPageSize());
        SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd");
        HontUser currUser = securityUtil.getCurrUser();
        // list.stream().collect(Collectors.joining(",", "", ""));
        List<String> flowTemplateIds = new ArrayList<>();
        if (StringUtils.isBlank(vo.getFlowTemplateId())){
            List<String> flowTemplateinfoIdsByUser = flowTemplateinfoUserAuthService.getFlowTemplateinfoIdsByUser(currUser.getId());
            if (flowTemplateinfoIdsByUser.size() > 0 && flowTemplateinfoIdsByUser != null){
                flowTemplateIds.addAll(flowTemplateinfoIdsByUser);
            }else {
                page.setTotalRows(0);
                page.setResultData(new ArrayList<>());
                return page;
            }
        }else {
            List<String> list = Arrays.asList(vo.getFlowTemplateId().split(","));
            flowTemplateIds.addAll(list);
        }
        IPage iIPage=new com.baomidou.mybatisplus.extension.plugins.pagination.Page(vo.getPageNumber(),vo.getPageSize());
        QueryWrapper<HkAssessmentInfo> wrapper=new QueryWrapper();
        wrapper.lambda().eq(StringUtils.isNotBlank(vo.getDepartmentId()),HkAssessmentInfo::getDepartmentId,vo.getDepartmentId());
        wrapper.lambda().eq(StringUtils.isNotBlank(vo.getPostId()),HkAssessmentInfo::getHontPostId,vo.getPostId());
        wrapper.lambda().eq(vo.getNodeName() != null,HkAssessmentInfo::getAssessmentStatus,vo.getNodeName());
        wrapper.lambda().in(flowTemplateIds.size() > 0,HkAssessmentInfo::getFlowTemplateId,flowTemplateIds);
        wrapper.lambda().like(StringUtils.isNotBlank(vo.getNickName()),HkAssessmentInfo::getNickName,vo.getNickName());
        wrapper.lambda().orderByDesc(HkAssessmentInfo::getCreateTime);
        IPage iPage = hkAssessmentInfoMapper.selectPage(iIPage, wrapper);
        page.setTotalRows((int)iPage.getTotal());
        List<HkAssessmentInfo> records = iPage.getRecords();
        List<HkAssessmentInfoAndFlowVo> result=new com.spire.ms.System.Collections.ArrayList();
        List<String> listProcess = new ArrayList<>();
        List<String> processIds = new ArrayList<>();
        for(int i=0;i<records.size();i++){
            HkAssessmentInfoAndFlowVo hkAssessmentInfoAndFlowVo=new  HkAssessmentInfoAndFlowVo();
            hkAssessmentInfoAndFlowVo.setDepartmentTitle(records.get(i).getDepartmentTitle());
            hkAssessmentInfoAndFlowVo.setTime(dateformat.format( records.get(i).getCreateTime()));
            hkAssessmentInfoAndFlowVo.setProcessInstanceId( records.get(i).getProcessInstanceId());
            hkAssessmentInfoAndFlowVo.setScore(records.get(i).getAssessmentScore());
            hkAssessmentInfoAndFlowVo.setAssessmentStatus(records.get(i).getAssessmentStatus());
            hkAssessmentInfoAndFlowVo.setHontUserId(records.get(i).getHontUserId());
            hkAssessmentInfoAndFlowVo.setNickName(records.get(i).getNickName());
            hkAssessmentInfoAndFlowVo.setId(records.get(i).getId());
            hkAssessmentInfoAndFlowVo.setPostTitle(records.get(i).getHontPostTitle());
            processIds.add(records.get(i).getProcessInstanceId());
            if(!records.get(i).getAssessmentStatus().equals("2")){
                listProcess.add(records.get(i).getProcessInstanceId());
            }else{
                hkAssessmentInfoAndFlowVo.setNodeName("考核结束");
            }
            result.add(hkAssessmentInfoAndFlowVo);
        }
        List<InitiatorDateTypeVo> initiatorCountDate = flowInstanceinfoMapper.getInitiatorCountDate(processIds);
        result.stream().map(m -> {
            initiatorCountDate.stream().filter(m2-> Objects.equals(m.getProcessInstanceId(),m2.getId())).forEach(m2-> {
                m.setInitiator(m2.getInitiator());
                if (m2.getEndTime() != null){
                    Map<String, Object> datePoorMap = DateUtils.getDatePoorMap(m2.getEndTime(), m2.getStartTime());
                    m.setElapsedTime(datePoorMap.get("elapsedTime").toString());
                    m.setElapsedTimeStatus(datePoorMap.get("elapsedTimeStatus").toString());
                }else{
                    m.setElapsedTime("/");
                }
                m.setFlowTemplateName(m2.getFlowTemplateName());
            });
            return m;
        }).collect(Collectors.toList());

        if(listProcess.size()>0){
            List<FlowNodeinfoOnInstanceInfoVo> nodeByInstanceIds = flowNodeinfoMapper.getNodeByInstanceIds(listProcess);
            Map<String, String> collect = nodeByInstanceIds.stream().collect(Collectors.toMap(FlowNodeinfoOnInstanceInfoVo::getInstanceId, FlowNodeinfoOnInstanceInfoVo::getNodeName));
          for(int i=0;i<result.size();i++){
              if(collect.containsKey(result.get(i).getProcessInstanceId())){
                  result.get(i).setNodeName(collect.get(result.get(i).getProcessInstanceId()));
              }
          }
        }
        page.setResultData(result);
        return page;
    }

    @Override
    public HkassessmentScoreAndRecordVo getHkAssessmentScoreDetial(String processInstanceId) {
        List<HkAssessmentScore> list = hkAssessmentScoreDao.findAll(new Specification<HkAssessmentScore>() {
            @Nullable
            @Override
            public Predicate toPredicate(Root<HkAssessmentScore> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {

                // TODO 可添加你的其他搜索过滤条件 默认已有创建时间过滤
                Path<String> createTimeField = root.get("processInstanceId");

                List<Predicate> list = new ArrayList<Predicate>();

                // 创建时间
                list.add(cb.equal(createTimeField,processInstanceId));

                Predicate[] arr = new Predicate[list.size()];
                cq.where(list.toArray(arr));

                return null;
            }
        });
        DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        List<HkAssessmentRecordVo> records=new ArrayList<HkAssessmentRecordVo>();
        FlowInstanceinfo flowInstanceinfo = flowInstanceinfoMapper.selectById(processInstanceId);
        QueryWrapper<FlowHistory> query = Wrappers.query();
        query.lambda().eq(FlowHistory::getFlowInstanceId,processInstanceId);
        List<FlowHistory> flowHistories = flowHistoryMapper.selectList(query);
        if (flowInstanceinfo != null){
            HkAssessmentRecordVo record=new HkAssessmentRecordVo();
            record.setTime(flowInstanceinfo.getFlowCreateTime().format(fmt));
            record.setNickName(flowInstanceinfo.getFlowHandler());
            record.setAssessmentStatus("考核发起人");
            records.add(record);
        }
        if (flowHistories.size() > 0){
            for (int i = 0; i < flowHistories.size(); i++) {
                HkAssessmentRecordVo record=new HkAssessmentRecordVo();
                record.setTime(flowHistories.get(i).getTaskCreateTime().format(fmt));

                if (flowHistories.get(i).getTaskEndTime() == null){
                    record.setAssessmentStatus("未审核");
                    FlowTaskInstance flowTaskInstanceByFlowInstance = flowTaskInstanceService.getFlowTaskInstanceByFlowInstance(flowHistories.get(i).getFlowInstanceId());
                    List<String> approvalUsers = flowTaskHandlerMapper.getApprovalUsers(flowTaskInstanceByFlowInstance.getId());
                    if (approvalUsers.size() > 0){
                        String join = Joiner.on(",").join(approvalUsers);
                        record.setNickName(join);
                    }
                    Map<String, Object> dateTimePoor = DateUtils.getDateTimePoor(LocalDateTime.now(), flowHistories.get(i).getTaskCreateTime());
                    record.setElapsedTime(dateTimePoor.get("elapsedTime").toString());
                    record.setElapsedTimeStatus(dateTimePoor.get("elapsedTimeStatus").toString());
                }else {
                    record.setAssessmentStatus("审核通过");
                    Map<String, Object> dateTimePoor = DateUtils.getDateTimePoor(flowHistories.get(i).getTaskEndTime(), flowHistories.get(i).getTaskCreateTime());
                    record.setElapsedTime(dateTimePoor.get("elapsedTime").toString());
                    record.setElapsedTimeStatus(dateTimePoor.get("elapsedTimeStatus").toString());
                    Optional<HontUser> byId = hontUserDao.findById(flowHistories.get(i).getTaskHandler());
                    record.setNickName( byId.get().getNickName());

                }

                records.add(record);
            }
        }

        List<String> approvalId=new ArrayList<>();



//        for(int i=0;i<list.size();i++){
//            if(!approvalId.contains(list.get(i).getApprovalUserId())){
//                approvalId.add(list.get(i).getApprovalUserId());
//                HkAssessmentRecordVo record=new HkAssessmentRecordVo();
//                record.setTime(format.format(list.get(i).getCreateTime()));
//                record.setNickName(list.get(i).getApprovalUserId());
//                records.add(record);
//            }
//        }
        Iterator<HkAssessmentScore> iterator = list.iterator();
      while (iterator.hasNext()){
          HkAssessmentScore next = iterator.next();
          if(!next.getIsCurrentAssessment().equals("1")){
              iterator.remove();
          }
      }
        HkassessmentScoreAndRecordVo vo=new HkassessmentScoreAndRecordVo();
        vo.setHkAssessmentRecordVos(records);
            vo.setHkAssessmentScores(list);
        return vo;
    }

    @Override
    public List<ScoreAndCommentHistoryVo> getItemScoreAndCommentHistory(ItemAndProcessIdVo vo) {
        List<HkAssessmentScore> list = hkAssessmentScoreDao.findAll(new Specification<HkAssessmentScore>() {
            @Nullable
            @Override
            public Predicate toPredicate(Root<HkAssessmentScore> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {

                // TODO 可添加你的其他搜索过滤条件 默认已有创建时间过滤
                Path<String> createTimeField = root.get("processInstanceId");
                Path<String> indexIdField = root.get("indexId");
                List<Predicate> list = new ArrayList<Predicate>();

                // 创建时间
                list.add(cb.equal(createTimeField,vo.getProcessInstanceId()));
                list.add(cb.equal(indexIdField,vo.getItemId()));
                Predicate[] arr = new Predicate[list.size()];
                cq.where(list.toArray(arr));

                return null;
            }
        });
        List<ScoreAndCommentHistoryVo> resultList=new ArrayList<>();

        for(int i=0;i<list.size();i++){
            ScoreAndCommentHistoryVo historyVo=new ScoreAndCommentHistoryVo();
            historyVo.setComment(list.get(i).getIndexComment());
            historyVo.setScore(list.get(i).getScore());
            Optional<HontUser> byId = hontUserDao.findById(list.get(i).getApprovalUserId());
            historyVo.setNickName(byId.get().getNickName());
            resultList.add(historyVo);
        }
        return resultList;
    }

    public void synchronizationTemplateId(){
        List<HkAssessmentInfo> all = getAll();
        List<String> prIds = new ArrayList<>();

        all.forEach(hkAssessmentInfo -> {
            prIds.add(hkAssessmentInfo.getProcessInstanceId());
        });
        List<FlowInstanceinfo> flowInstanceinfos = flowInstanceinfoMapper.selectBatchIds(prIds);
        all.stream().map(m -> {
            flowInstanceinfos.stream().filter(m2 -> Objects.equals(m.getProcessInstanceId(), m2.getId())).forEach(m2 -> {
                m.setFlowTemplateId(m2.getTemplateId());
            });
            return m;
        });
        saveOrUpdateAll(all);
    }
}